package com.af.system.util;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * @author : zhenyun.su
 * @comment : 用于处理 HttpServletRequest，  HttpServletResponse
 * 功能说明：
 * 1. redirectJson， redirectDate, redirectPage 用于重写返回值
 * 2. getAppUrl(request, String queryPath) 返回  http://hostname:port/contextpath+path
 * 3. spliceUrl(String url, Map<String, Object> params) 返回： 拼接url地址，根据Map类型，返回url字符串值
 * 4. setResponseFile 用于下载文件，设置HttpServletResponse 媒体类型
 * 2021/02/20 ----
 *  setResponseExcel() 用于下载Excel，设置HttpServletResponse 媒体类型
 * <p>
 * SUCCESS = 200;  请求成功
 * SERVER_FAILURE = -1; 服务后端异常
 * RETRY = -3;  网络异常，可重试
 * FAILURE = -999;  其他异常
 * @since : 2019/12/03
 */

public final class AfServletUtils {
    public static final String OK_CODE = "200";
    public static final String OK_INFO = "success";
    public static final String FAIL_INFO = "failure";
    public static final int SUCCESS = 200;
    public static final int SERVER_FAILURE = -1;
    public static final int RETRY = -3;
    public static final int FAILURE = -999;
    public final static String APP_HTML = "text/html; charset=UTF-8";
    public final static String APP_JSON = "application/json; charset=UTF-8";
    public final static String APP_XML = "application/xml; charset=UTF-8";
    public final static String APP_FILE = "application/octet-stream;charset=UTF-8";
    public final static String APP_EXCEL = "application/vnd.ms-excel;charset=UTF-8";
    public final static String APP_FORM = "application/x-www-form-urlencoded; charset=UTF-8";

    private final static Pattern ABSOLUTER_URL_PATTERN = Pattern.compile("\\A[a-z0-9.+-]+://.*", 2);
    public static final String COOKIE_LANG = "clientLanguage";
    public static final String COOKIE_THEME = "clientTheme";

    /**
     * @comment : 获取cookie值
     * 比如获取语言，或主题的cookie值
     */
    public static String cookieValue(HttpServletRequest request, String name) {
        Cookie[] cookies = request.getCookies();
        for (int i = 0; i < cookies.length; i++) {
            Cookie cookie = cookies[i];
            if (name.equalsIgnoreCase(cookie.getName())) {
                return cookie.getValue();
            }
        }
        return null;
    }

    /**
     * @comment : 从cookie值，获取locale
     */
    public static Locale getRequestLocale(HttpServletRequest request) {
        try {
            String lang = AfServletUtils.cookieValue(request, COOKIE_LANG);
            if (lang != null) {
                return Locale.forLanguageTag(lang);
            }
            return Locale.getDefault();
        } catch (Exception e) {
            return Locale.getDefault();
        }
    }
    /**
     * @comment : 从cookie值，获取locale
     */
    public static Locale getRequestLocale(String lang) {
        try {
            if (lang != null) {
                return Locale.forLanguageTag(lang);
            }
            return Locale.getDefault();
        } catch (Exception e) {
            return Locale.getDefault();
        }
    }

    /**
     * @comment : 重写返回值，
     * redirectPage：重定位到url
     * redirectJson: 按json重写
     * redirectDate: 按contentType 格式重写
     * 参考：spring的DefaultRedirectStrategy(返回页面) 来开发
     */
    public static void redirectJson(HttpServletResponse response, String context) throws IOException {
        redirectData(response, context, APP_JSON);
    }

    public static void redirectPage(HttpServletRequest request, HttpServletResponse response, String url) throws
            IOException {
        String redirectUrl = AfServletUtils.calculateRedirectUrl(request.getContextPath(), url, false);
        redirectUrl = response.encodeRedirectURL(redirectUrl);
        response.setContentType(AfServletUtils.APP_HTML);
        response.sendRedirect(redirectUrl);
    }

    public static void redirectData(HttpServletResponse response, String context, String contentTyp) throws
            IOException {
        response.setContentType(contentTyp);
        response.getWriter().write(context);
    }


    /**
     * @return : http://hostname:port/contextpath/ +queryPath
     * @comment: 根据HttpServletRequest 获取url地址
     */
    public static String getAppUrl(HttpServletRequest request, String queryPath) {
        StringBuilder sb = new StringBuilder("http://");
        sb.append(request.getServerName()).append(":").append(request.getServerPort())
                .append(request.getContextPath())
                .append("/");
        if (queryPath != null) {
            sb.append(queryPath);
        }
        return sb.toString();
    }

    /**
     * @comment : 拼接url地址，根据Map类型，返回url字符串值
     */
    public String spliceUrl(String url, Map<String, Object> params) {
        StringBuilder builder = new StringBuilder(url);
        boolean isFirst = true;
        for (String key : params.keySet()) {
            if (key != null && params.get(key) != null) {
                if (isFirst) {
                    isFirst = false;
                    builder.append("?");
                } else {
                    builder.append("&");
                }
                builder.append(key)
                        .append("=")
                        .append(params.get(key).toString());
            }
        }
        return builder.toString();
    }

    /**
     * @comment : 计算返回url地址
     */
    public static String calculateRedirectUrl(String contextPath, String url, Boolean isRelative) {
        if (!isAbsoluteUrl(url)) {
            return isRelative ? url : contextPath + url;
        } else if (!isRelative) {
            return url;
        } else if (!url.contains(contextPath)) {
            return "";
        } else {
            url = url.substring(url.lastIndexOf("://") + 3);
            url = url.substring(url.indexOf(contextPath) + contextPath.length());
            if (url.length() > 1 && url.charAt(0) == '/') {
                url = url.substring(1);
            }
            return url;
        }
    }

    /**
     * @comment : 判断url地址，是否为http:// 开头的绝对地址
     */
    public static boolean isAbsoluteUrl(String url) {
        if (url == null) {
            return false;
        } else {
            return ABSOLUTER_URL_PATTERN.matcher(url).matches();
        }
    }

    /**
     * @comment : 用于下载文件，设置HttpServletResponse 媒体类型
     */
    public static void setResponseFile(HttpServletResponse response, String fileName, Integer len) {
        response.reset();
        response.setContentType(APP_FILE);
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
        response.addHeader("Content-Length", "" + len);
        response.setHeader("filename", fileName);
        response.setHeader("Access-Control-Expose-Headers", "filename,Content-Disposition");

    }
    /**
     * @comment : 用于下载Excel文件，设置HttpServletResponse 媒体类型
     */
    public static void setResponseExcel(HttpServletResponse response, String fileName, Integer len) {
        response.reset();
        response.setContentType(APP_EXCEL);
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
        response.addHeader("Content-Length", "" + len);
        response.setHeader("filename", fileName);
        response.setHeader("Access-Control-Expose-Headers", "filename,Content-Disposition");

    }

    /**
     * @comment : 配合easyExcel下载
     */
    public static void setResponseExcel(HttpServletResponse response, String fileName) {
        response.reset();
        response.setContentType(APP_EXCEL);
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
        response.setHeader("filename", fileName);
        response.setHeader("Access-Control-Expose-Headers", "filename,Content-Disposition");
    }
    /**
     * @comment : 用于下载Excel文件，设置HttpServletResponse 媒体类型
     */
    public static void setResponseHtml(HttpServletResponse response) {
        response.reset();
        response.setContentType(APP_HTML);
    }
}
